import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PMatrix3D;
import processing.core.PVector;


public class Player {
	private static final int MAX_SPEED = 15; //maksimi liikkumisnopeus, suhteellinen yksikkö

	Tuberunner p;

	private float angle;
	private int hp;
	private boolean immune, immutesti;
	public boolean kuollut;
	private float immutimer;
	private boolean nakymaton;

	private PVector paikka;
	private int speed = 0;
//	private float xkerroin = 0, ykerroin = 0;
	private Hahmo graffa; // Taman avulla piirretaan 3d-mallinnus hahmosta.
	private PImage laiffi; // kuva elamasta eli sydamesta
	private TubeHallitsija th;

	private boolean left, right, both; // navigaation status
	private char vasen_nappi, vasen_nappi_alt, oikea_nappi, oikea_nappi_alt; // interaktio-n�pp�imet
	public int playerNum; // pelaaja-nro

	/**
	 * Luokka tietaa pelaajan paikan ja piirtaa sen Hahmon. Player tietaa myos pelaajan elamat eli laiffin.
	 * 
	 * @param father isanta PApplet
	 * @param player pelaajaNumero: 1, 2 tai 3.
	 * @param teho linkki tubeHallitsijaan
	 */
	public Player(Tuberunner father, int player, TubeHallitsija teho) {
		this.th = teho;
		this.paikka = new PVector(0,0,0);
		p = father;
		angle = 0;
		if (player < 1 || player > 3) {
			System.err.println("Virheellinen pelaaja nro!");
		}
		playerNum = player;
		this.nappiCalibraatio(this.playerNum);
		graffa = new Hahmo(father, true, this.playerNum);
		this.hp = 3;
		this.initLifeImage();
	}

	// lataa pelaaajaa korreloivan sydamen kuvan
	private void initLifeImage() {
		if (this.playerNum == 1) {
			this.laiffi = p.loadImage("textures/Vihreasydan.png");
		}
		else if (this.playerNum == 2) {
			this.laiffi = p.loadImage("textures/pinkkisydan.png");
		}
		else if (this.playerNum == 3) {
			this.laiffi = p.loadImage("textures/ruskeasydan.png");
		}
	}

	public void nappaimisto(boolean vasen) {
		// K��ntelem�ll� kulmaa (angle) pelaajan paikka muuttuu toistaiseksi t�ss� tuubissa
		if (vasen) {
			this.angle += PApplet.PI / 15;
		}
		else {
			this.angle -= PApplet.PI / 15;
		}
		if (this.angle < PApplet.PI) {
			this.angle += 2 * PApplet.PI;
		}
		else if (this.angle > PApplet.PI) {
			this.angle -= 2 * PApplet.PI;
		}
	}
	public boolean osuuko()
	{
		/*
		 * osumatesti katsoo viidennen poikkileikkauksen (jonka p��ll� mursu on aina) esteen sijainnin
		 * ympyr�lt� (v�lille 0-30)
		 * ja pelaajan mursun sijainnin samoin tavoin ympyr�lt� (v�lille 0-30)
		 * n�it� vertaillaan kesken��n ja jos niiden v�linen ero < 2 tulkitaan se osumaksi.
		 * 
		 */
		int e = this.th.getPl().get(5).getEstePositio();
		//System.out.println("esteen positio on "+e);
		float apu = -angle +2*PApplet.PI;// 0-2PI kello 12 l�htien my�t�p�iv��
		if(apu>2*PApplet.PI)
		{
			apu -= 2*PApplet.PI;
		}
		float oma =  (apu/(2*PApplet.PI))*30;
		//System.out.println("oma positiosi on "+oma);
		if(oma <= 2.0)
		{
			if(PApplet.abs(oma-e+30)<=3)//jos pelaaja on kohdassa 1 ja este kohdassa 30 pitaa tulla collision
			{
				return true;
			}
		}
		if(oma >= 28.0)
		{
			if(PApplet.abs(oma-e-30)<=3)//sama toisin pain
			{
				return true;
			}
		}
		//normaalitapaus
		if(PApplet.abs(e-oma)<=3)//3 = osumav�li on 4/30 osaa koko ympyr�st�
		{
			return true;
		}
		else return false;
	}
	public void kerroMatriisilla(PMatrix3D matriisi)
	{
		matriisi.mult(this.paikka, this.paikka);
	}

	// tekee mursusta immuunin 3s ajan, ja laskee kuinka mursun vilkkuminen hoituu
	private void immune()
	{
		if(immune)
		{
			if(immutesti)
			{
				immutesti = false;
				this.immutimer = p.millis();
			}

			// lopetetaan mursun immuniteetti ja vilkkuminen 3000ms kuluttua
			if((p.millis()-immutimer) > 3000)
			{
				this.immune = false;
				this.nakymaton = false;
			}

			// Mursun vilkkuminen toteutuu cosinilauseen +/- -arvojen kautta.
			else if (Math.cos((p.millis()-immutimer) /150 * PApplet.PI) > 0) {
				this.nakymaton = true;
			}
			else {
				this.nakymaton = false;
			}
		}
	}
	public void kuoli()
	{
		this.kuollut = true;
		// Snif. :'(
	}
	public void draw()
	{
		this.immuuniTestit();
		this.pelaajanPaikka();

		if (!this.nakymaton) { // ei piirreta mursua mikali immuuninakymattomyys on voimassa
			graffa.mursu(); //piirt�� mursun
		}

		p.popMatrix();
		this.paikka = new PVector(0,0,0);

		if (!this.nakymaton) { // ei piirreta sydamia mikali immuuninakymattomyys on voimassa
			this.laiffiStatus();
		}

		this.nopeusHallinta(); //hoitaa tyypin liikuttelun ja nopeuden
	}

	// piirtaa sydamet eli mursun laiffin
	private void laiffiStatus() {
		int x;
		if (this.playerNum == 1) {
			x = -65;
		}
		else if (this.playerNum == 2) {
			x = 35;
		}
		else {
			x = -15;
		}
		for (int l = 1; l <= this.hp; l++) {	// piirretaan sydamet
			p.pushMatrix();
			//			p.rotateY(PApplet.PI);
			p.translate(0, 0, 40);
			p.image(laiffi, x, -60, 10, 10);
			x += 11;


			p.popMatrix();
		}
	}

	// tehdaan immuniteettiin liittyvat tarkastukset
	private void immuuniTestit() {
		this.immune();
		if(!immune)
		{
			if(osuuko())
			{
				this.hp--;
				this.immune=this.immutesti = true;
				if(this.hp<=0)
				{
					this.kuoli(); // kyynel :'(
				}
			}
		}
	}

	private void pelaajanPaikka() {
		//lasketaan pelaajan paikka
		this.paikka.y = PApplet.cos(-this.angle)*(this.p.annaRadius()) ;
		this.paikka.x = PApplet.sin(-this.angle)*(this.p.annaRadius()) ;
		this.paikka.z = 0;

		for(int a = 0; a < 5; a++)
		{
			this.kerroMatriisilla(this.th.getPl().get(a).getMat());
		}
		int korjaus = this.th.getPl().get(0).dz;
		float xkorjaus = (this.th.getPl().get(5).rotateX*1000-korjaus)*5*this.th.getPl().get(5).rotateX;
		float ykorjaus = (this.th.getPl().get(5).rotateY*1000-korjaus)*5*this.th.getPl().get(5).rotateY;
		//this.paikka.z = 100;

		p.pushMatrix();

		p.translate(this.paikka.x+xkorjaus, this.paikka.y-ykorjaus, this.paikka.z-korjaus);
		p.scale((float) 0.5);
		p.rotateZ(this.angle);
		//		p.rotateY((float)(this.angle*0.2));
		//p.box(20);
	}

	private void nopeusHallinta() {

		if (this.speed < 0) { // jos nykyinen vauhti on vasemmalle
			if (this.left && Math.abs(this.speed) < MAX_SPEED) { // kiihdytetään vasempaan, mikäli mahdollista
				this.speed -= 1;
			}
			else if (this.right) { //jarrutus takaisin oikealle nopeampaa
				this.speed += 4;
			}
		}
		else if (this.speed > 0) {
			if (this.right && this.speed < MAX_SPEED) {
				this.speed += 1;
			}
			else if (this.left) {
				this.speed -= 4;
			}
		}
		else if (this.left) {
			this.speed -= 1;
		}
		else if (this.right) {
			this.speed += 1;
		}
		if (this.speed != 0 && !this.left && !this.right) { // jos ei kiihdytetä ollenkaan....
			// hidastetaan vauhtia
			if (this.speed > 0) {
				this.speed -= 3;
				if (this.speed < 0) {
					this.speed = 0;
				}
			}
			else {
				this.speed += 3;
				if (this.speed > 0) {
					this.speed = 0;
				}
			}
		}

		this.angle += this.speed * PApplet.PI / 150; // siirretään mursua muuttamalla sen "kulmaa"

		// kulman pyoraytys, jotta angle kuuluu valille [-PI, PI]
		if(this.angle < -PApplet.PI)
		{
			this.angle += 2*PApplet.PI;
		}
		if(this.angle > PApplet.PI)
		{
			this.angle -= 2*PApplet.PI;
		}
	}

	// Kalibroidaan 2- ja 3-pelaajien nappulat.
	// [ 1-pelaaja oli pakko hardcodata, koska nuolin�pp�imet eiv�t ole ASCII-n�pp�imi�. ]
	private void nappiCalibraatio(int pelaaja) {
		if (pelaaja == 2) {
			this.vasen_nappi = "a".charAt(0);
			this.vasen_nappi_alt = "A".charAt(0);
			this.oikea_nappi = "s".charAt(0);
			this.oikea_nappi_alt = "S".charAt(0);
		}
		else if (pelaaja == 3) {
			this.vasen_nappi = "h".charAt(0);
			this.vasen_nappi_alt = "H".charAt(0);
			this.oikea_nappi = "j".charAt(0);
			this.oikea_nappi_alt = "J".charAt(0);
		}
	}

	// K�sitell��n n�pp�imen painallus
	public void keyPressed() {
		if (this.playerNum == 1 && p.keyCode == PApplet.LEFT || p.key == this.vasen_nappi || p.key == this.vasen_nappi_alt) {
			this.left = true;
			if (this.right) {
				this.right = false;
				this.both = true;
			}
		}
		else if (this.playerNum == 1 && p.keyCode == PApplet.RIGHT || p.key == this.oikea_nappi || p.key == this.oikea_nappi_alt) {
			this.right = true;
			if (this.left) {
				this.left = false;
				this.both = true;
			}
		}
	}

	// K�sitell��n n�pp�imen irrotus
	public void keyReleased() {
		if (this.playerNum == 1 && p.keyCode == PApplet.LEFT || p.key == this.vasen_nappi || p.key == this.vasen_nappi_alt) {
			this.left = false;
			if (this.both) {
				this.right = true;
				this.both = false;
			}
		}
		else if (this.playerNum == 1 && p.keyCode == PApplet.RIGHT || p.key == this.oikea_nappi || p.key == this.oikea_nappi_alt) {
			this.right = false;
			if (this.both) {
				this.left = true;
				this.both = false;
			}
		} 	
	}
}

